﻿using System;
using System.Text;
#if WINDOWS_PHONE
using System.Net;
using System.Windows;
#elif SILVERLIGHT
using System.Windows.Browser;
using System.Windows;
#elif WINRT
using System.Net;
using Windows.Foundation;
using HttpUtility = System.Net.WebUtility;
#else
using System.Web;
using System.Windows;
#endif

namespace Esponce.QRCode
{
	public class QRCodeUriBuilder
	{
		#region Public properties
		public string BaseUrl
		{
			get;
			set;
		}

		public string ApiKey
		{
			get;
			set;
		}
		#endregion

		#region Public methods
		/// <summary>
		/// Gets a URL for "generate" method.
		/// </summary>
		/// <param name="model">Object containing content and parameters to generate a QR Code.</param>
		/// <param name="attachment">A value indicating whether to offer file as download. Usually used in web browsers.</param>
		/// <param name="filename">Optionally suggested file name for attachment. Only when "attachment" parameter is set to "true"</param>
		/// <returns></returns>
		public string BuildGenerateUrl(QRCodeModel model, bool attachment = false, string filename = null)
		{
			var builder = new StringBuilder();
			builder.Append(this.BaseUrl).Append("generate");

			builder.Append("?content=").Append(HttpUtility.UrlEncode(model.Content));

			if (!string.IsNullOrEmpty(model.Format))
			{
				builder.Append("&format=").Append(HttpUtility.UrlEncode(model.Format));
			}

			if (model.Padding >= 0)
			{
				builder.Append("&padding=").Append(model.Padding.ToString());
			}

			if (!model.ImageSize.IsEmpty)
			{
				builder.Append("&size=").AppendFormat("{0}x{1}", model.ImageSize.Width, model.ImageSize.Height);
			}
			else if (model.Size > 0)
			{
				builder.Append("&size=").Append(model.Size);
			}

			if (model.Version > 0 && model.Version <= 40)
			{
				builder.Append("&version=").Append(model.Version.ToString());
			}

			if (model.EncodeMode != QREncodeMode.Default)
			{
				builder.Append("&em=").Append(model.EncodeModeString);
			}

			if (model.ErrorCorrection != QRErrorCorrection.Default && model.ErrorCorrection != QRErrorCorrection.Unknown)
			{
				builder.Append("&ec=").Append(model.ErrorCorrectionString);
			}

			if (model.BackgroundString != null)
			{
				builder.Append("&background=").Append(HttpUtility.UrlEncode(model.BackgroundString));
			}

			if (model.ForegroundString != null)
			{
				builder.Append("&foreground=").Append(HttpUtility.UrlEncode(model.ForegroundString));
			}

			if (!string.IsNullOrEmpty(model.Shorten))
			{
				builder.Append("&shorten=").Append(model.Shorten);
			}

			if (attachment)
			{
				builder.Append("&attachment=true");
				if (!string.IsNullOrEmpty(filename))
				{
					builder.Append("&filename=" + HttpUtility.UrlEncode(filename));
				}
			}

			if (!string.IsNullOrEmpty(this.ApiKey))
			{
				builder.Append("&auth=").Append(this.ApiKey);
			}

			return builder.ToString();
		}

		public string BuildDecodeUrl(string format = null)
		{
			var builder = new StringBuilder();
			builder.Append(this.BaseUrl).Append("decode");

			if (!string.IsNullOrEmpty(format))
			{
				builder.Append("?format=").Append(format);
			}
			if (!string.IsNullOrEmpty(this.ApiKey))
			{
				string binder = !string.IsNullOrEmpty(format) ? "&" : "?";
				builder.Append(binder).Append("auth=").Append(this.ApiKey);
			}

			string url = builder.ToString();
			return url;
		}

		public string BuildTrackListUrl()
		{
			if (string.IsNullOrEmpty(this.ApiKey))
			{
				throw new ArgumentException("API key is missing!");
			}

			string url = string.Format("{0}track/list?auth={1}", this.BaseUrl, this.ApiKey);
			return url;
		}

		public string BuildTrackCampaignUrl(string id = null)
		{
			if (string.IsNullOrEmpty(this.ApiKey))
			{
				throw new ArgumentException("API key is missing!");
			}

			string url;
			if (!string.IsNullOrEmpty(id))
			{
				url = string.Format("{0}track/campaign/{2}?auth={1}", this.BaseUrl, this.ApiKey, id);
			}
			else
			{
				url = string.Format("{0}track/campaign?auth={1}", this.BaseUrl, this.ApiKey);
			}
			return url;
		}

		public string BuildTrackQRCodeUrl(string id = null)
		{
			if (string.IsNullOrEmpty(this.ApiKey))
			{
				throw new ArgumentException("API key is missing!");
			}

			string url;
			if (!string.IsNullOrEmpty(id))
			{
				url = string.Format("{0}track/qrcode/{2}?auth={1}", this.BaseUrl, this.ApiKey, id);
			}
			else
			{
				url = string.Format("{0}track/qrcode?auth={1}", this.BaseUrl, this.ApiKey);
			}
			return url;
		}

		public string BuildTrackStatisticsUrl(string id, ExportFormat format)
		{
			if (string.IsNullOrEmpty(this.ApiKey))
			{
				throw new ArgumentException("API key is missing!");
			}

			string outputFileExtension = null;

			switch (format)
			{
				case ExportFormat.CSV:
					outputFileExtension = "csv";
					break;

				case ExportFormat.XLS:
					outputFileExtension = "xls";
					break;

				case ExportFormat.XML:
					outputFileExtension = "xml";
					break;

				case ExportFormat.JSON:
					outputFileExtension = "json";
					break;

				default:
					throw new NotImplementedException();
			}

			string url = string.Format("{0}track/statistics/{1}.{2}?auth={3}", this.BaseUrl, id, outputFileExtension, this.ApiKey);
			return url;
		}

		public string BuildTrackExportUrl(ExportFormat format)
		{
			if (string.IsNullOrEmpty(this.ApiKey))
			{
				throw new ArgumentException("API key is missing!");
			}

			string itemFileExtension = null;
			string outputFileExtension = null;

			switch (format)
			{
				case ExportFormat.CSV:
					outputFileExtension = "csv";
					break;

				case ExportFormat.XLS:
					outputFileExtension = "xls";
					break;

				case ExportFormat.XML:
					outputFileExtension = "xml";
					break;

				case ExportFormat.JSON:
					outputFileExtension = "json";
					break;

				case ExportFormat.ZIP_PNG:
					outputFileExtension = "zip";
					itemFileExtension = "png";
					break;

				case ExportFormat.ZIP_EPS:
					outputFileExtension = "zip";
					itemFileExtension = "eps";
					break;

				case ExportFormat.ZIP_SVG:
					outputFileExtension = "zip";
					itemFileExtension = "svg";
					break;

				default:
					throw new NotImplementedException();
			}

			string url = string.Format("{0}track/export.{1}?auth={2}", this.BaseUrl, outputFileExtension, this.ApiKey);
			if (itemFileExtension != null)
			{
				url += "&format=" + itemFileExtension;
			}

			return url;
		}

		public string BuildTrackImportUrl(ImportFormat format)
		{
			if (string.IsNullOrEmpty(this.ApiKey))
			{
				throw new ArgumentException("API key is missing!");
			}

			string inputFileExtension = null;

			switch (format)
			{
				case ImportFormat.CSV:
					inputFileExtension = "csv";
					break;

				case ImportFormat.XLS:
					inputFileExtension = "xls";
					break;

				case ImportFormat.XML:
					inputFileExtension = "xml";
					break;

				case ImportFormat.JSON:
					inputFileExtension = "json";
					break;

				case ImportFormat.ZIP_PNG:
					inputFileExtension = "zip";
					break;

				default:
					throw new NotImplementedException();
			}

			string url = string.Format("{0}track/import?auth={2}&format={1}", this.BaseUrl, inputFileExtension, this.ApiKey);
			return url;
		}
		#endregion
	}
}
